#include <sw/redis++/redis++.h>
#include <iostream>
#include <optional>

using namespace sw::redis;

// 默认只会存内存不落盘
int main() {
    try {
        // Create a Redis object, which is movable but NOT copyable.
        auto redis = Redis("tcp://127.0.0.1:6379");

        // ***** STRING commands *****

        redis.set("key", "value");
        auto val = redis.get("key");    // val is of type OptionalString.
        if (val) {
            std::cout << "Get key: " << *val << std::endl;
        }

        // ***** LIST commands *****
        redis.lpush("list", "val");
        redis.rpush("list", "val");
        // Pop an element from the beginning of the list
        auto elem = redis.lpop("list");
        if (elem) {
            std::cout << "LPOP element: " << *elem << std::endl;
        }

        // ***** HASH commands *****
        redis.hset("hash", "field", "value");
        auto hval = redis.hget("hash", "field");
        if (hval) {
            std::cout << "HGET field: " << *hval << std::endl;
        }

        // ***** Transaction *****
        auto tx = redis.transaction();
        auto tx_replies = tx.hmset("hash", {std::make_pair("f1", "v1"), std::make_pair("f2", "v2")})
                            .lpush("list", {"a", "b", "c"})
                            .incr("num")
                            .exec();

        std::cout << "Transaction executed successfully" << std::endl;

        // ***** Pipeline *****
        // auto pipe = redis.pipeline();
        // auto pipe_replies = pipe.set("key", "value")
        //                         .get("key")
        //                         .strlen("key")
        //                         .exec();

        // // Parse reply with reply::parse, which has the same interface as Redis::command
        // auto set_cmd_result = reply::parse<bool>(*pipe_replies.get(0));
        // auto get_cmd_result = reply::parse<OptionalString>(*pipe_replies.get(1));
        // auto strlen_cmd_result = reply::parse<long long>(*pipe_replies.get(2));

        // std::cout << "Pipeline results:" << std::endl;
        // std::cout << "SET result: " << set_cmd_result << std::endl;
        // if (get_cmd_result) {
        //     std::cout << "GET result: " << *get_cmd_result << std::endl;
        // }
        // std::cout << "STRLEN result: " << strlen_cmd_result << std::endl;

    } catch (const Error &e) {
        // Error handling
        std::cerr << "Redis error: " << e.what() << std::endl;
    }

    return 0;
}